﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Assets.Script.Config;


public class HeroBattleMgr : MonoBehaviourSingleton<HeroBattleMgr>
{
    public bool m_bPause = false;
    public float Speed
    {
        get { return m_fSpeed; }
        set
        {
            if (value < 0)
                return;
            m_fSpeed = value;
        }
    }
    private float m_fSpeed = 1;
    private Action m_funcLoadDone;

    //驱动战报
    //Buf缓存
    public Dictionary<int, Dictionary<int, BufData>> m_DicHeroBufs = new Dictionary<int, Dictionary<int, BufData>>();

    //英雄Spine资源
    public Dictionary<string, GameObject> m_DicSpines = new Dictionary<string, GameObject>();
    //所有的特效资源
    public Dictionary<string, GameObject> m_DicEffect = new Dictionary<string, GameObject>();


    //所有的英雄
    public List<BattleEntityHero> m_LisHeros = new List<BattleEntityHero>();
    //创建英雄需要的数据
    public List<HeroVo> m_lisCreateHero;


    //还没开始加载的状态
    public const int m_iNotReadyLoad = -100;
    //需要加载的spine英雄模型总数
    public int m_iSpineRes = 0;
    //需要加载的特效总数
    public int m_iEffectRes = 0;

    public void Init(List<HeroVo> heros,List<ActionNode> nodes,Action loadDone)
    {
        BattleEffectMgr.Instance.Init(HeroBattleStage.BattleBigType.Hero);
        //创建英雄需要的数据
        m_lisCreateHero = heros;
        //所有的行动节点
        m_lisActionNodes = nodes;
        //预加载资源  spine模型
        m_iSpineRes = m_iNotReadyLoad;
        m_iEffectRes = m_iNotReadyLoad;
        m_funcLoadDone = loadDone;
        LoadSpine();
        LoadEffect();
    }
    
    private void Update()
    {
        BattleEntityFactory.Instance.OnUpdate(m_fSpeed * Time.deltaTime);
        UpTimer(m_fSpeed * Time.deltaTime);
        BattleEffectMgr.Instance.OnUpdate(m_fSpeed * Time.deltaTime);
        EntityMessageDispatcher.Instance.OnUpdate(m_fSpeed * Time.deltaTime);

        if (Input.GetKeyDown(KeyCode.Q))
        {
            PlayNowActionNode();
        }
    }

    //创建英雄
    private void CreateHero()
    {
        for (int i = 0; i < m_lisCreateHero.Count; i++)
        {
            BattleEntityHero hero = BattleEntityFactory.Instance.CreateBtEntity<BattleEntityHero>();
            hero.OnCreate(m_lisCreateHero[i]);
            m_LisHeros.Add(hero);
        }
        for (int i = 0; i < m_lisActionNodes.Count; i++)
        {
            m_lisActionNodes[i].ConvertEntityId();
        }
    }
    //根据 reportId 知道entityId
    public int ConvertReportId2EntityId(int reportId)
    {
        for (int i = 0; i < m_LisHeros.Count; i++)
        {
            if(m_LisHeros[i].m_pHeroVo.reportId == reportId)
            {
                return m_LisHeros[i].Id;
            }
        }

        return 0;
    }

    #region Action_Node  Node->Entity(告诉实体干嘛)  Entity->Node(实体完成任务后告诉Node我完成了)
    //更新ActionNode
    List<ActionNode> m_lisActionNodes = new List<ActionNode>();
    private int m_iActionIndex = 0;
    public void HandleMessage(MessageBody msg)
    {
        m_lisActionNodes[m_iActionIndex].OnHandMessage(msg);
    }


    public void PlayActionNode(int nodeIndex)
    {
        if (nodeIndex < m_lisActionNodes.Count)
        {
            //把所有的spine order 都置为基础值
            for (int i = 0; i < m_LisHeros.Count; i++)
            {
                m_LisHeros[i].m_pRender.sortingOrder = HeroFightDef.c_iSpineBaseOrder;
            }
            //判断节点数据是否出错,如果出错那么此节点直接结束
            if (m_lisActionNodes[nodeIndex].NodeError())
            {
                Debug.Log(nodeIndex + "  节点出错了");
                ActionFinish(m_lisActionNodes[nodeIndex]);
            }
            else
            {
                m_lisActionNodes[nodeIndex].EnterNode();
            }
        }
        else
        {
            Debug.Log("超过行动节点个数  GG了");
            ActionNode_AllFinish();
        }
    }

    public void PlayNowActionNode()
    {
        PlayActionNode(m_iActionIndex);
    }

    public void ActionFinish(ActionNode node)
    {
        if (node.Index == m_iActionIndex)
        {
            m_iActionIndex++;
            PlayActionNode(m_iActionIndex);
        }
    }

    public void ActionNode_AllFinish()
    {
        for (int i = 0; i < m_LisHeros.Count; i++)
        {
            if (!m_LisHeros[i].IsDead())
            {
                m_LisHeros[i].ChangeState(BattleHeroState.c_sMState_Win);
            }
        }
    }
    #endregion


    //BUF 接口
    public void AddBuf(int entityId,BufData data)
    {
        if (!m_DicHeroBufs.ContainsKey(entityId))
            m_DicHeroBufs[entityId] = new Dictionary<int, BufData>();

        if(!m_DicHeroBufs[entityId].ContainsKey(data.bufId))
        {
            m_DicHeroBufs[entityId].Add(data.bufId, data);
        }
        else
        {
            m_DicHeroBufs[entityId][data.bufId].lifeTime = data.lifeTime;
        }
    }
    /// <summary>
    /// 减少Buf生命
    /// </summary>
    /// <param name="entityId">实例对象</param>
    /// <param name="bufId">BUF Id</param>
    /// <param name="life">0 的话就是删除,非0的话是扣除多少 </param>
    public void DelBuf(int entityId,int bufId,int life)
    {
        if (!m_DicHeroBufs.ContainsKey(entityId))
            return;

        if (!m_DicHeroBufs[entityId].ContainsKey(bufId))
            return;

        if(life != 0)
        {
            int less = m_DicHeroBufs[entityId][bufId].lifeTime - life;
            if (less < 0)
                less = 0;
            m_DicHeroBufs[entityId][bufId].lifeTime = less;
        }
        else
        {
            m_DicHeroBufs[entityId][bufId].lifeTime = 0;
        }
        if(m_DicHeroBufs[entityId][bufId].lifeTime == 0)
        {
            m_DicHeroBufs[entityId].Remove(bufId);
        }
    }

    //时间冻结
    public void FreezeTime(float time,float timeScale)
    {
        float oldSpeed = Speed;
        Speed = timeScale;
        AddTimer(delegate () {
            Speed = oldSpeed;
        }, time);
    }

    #region 美术资源模块管理
    //加载Spine
    private void LoadSpine()
    {
        List<string> modelPaths = new List<string>();
        for (int i = 0; i < m_lisCreateHero.Count; i++)
        {
            if (!modelPaths.Contains(m_lisCreateHero[i].model))
            {
                modelPaths.Add(m_lisCreateHero[i].model);
            }
        }
        m_iSpineRes = modelPaths.Count;

        for (int i = 0; i < modelPaths.Count; i++)
        {
            string path = modelPaths[i];
            AEResources.Load(path, typeof(GameObject), delegate (UnityEngine.Object obj)
            {
                m_iSpineRes--;
                GameObject gObj = obj as GameObject;
                m_DicSpines.Add(modelPaths[i], gObj);
                if (m_iSpineRes == 0)
                {
                    LoadDone();
                }
            });
        }
        if (m_iSpineRes == 0)
        {
            LoadDone();
        }
    }

    //加载特效, 子弹用到的特效,普攻用到的特效,技能用到的特效
    private void LoadEffect()
    {
        List<string> modelPath = new List<string>();
        for (int i = 0; i < m_lisActionNodes.Count; i++)
        {
            string effPath = null;
            SkillAction actionId = null;
            if (m_lisActionNodes[i].GetType() == typeof(Action_Attack_Slash)) {
                actionId = ((Action_Attack_Slash)m_lisActionNodes[i]).sActionConfig;
            }
            else if (m_lisActionNodes[i].GetType() == typeof(Action_Attack_Remote))
            {
                actionId = ((Action_Attack_Remote)m_lisActionNodes[i]).sActionConfig;
            }
            else if (m_lisActionNodes[i].GetType() == typeof(Action_Attack_Skill))
            {
                actionId = ((Action_Attack_Skill)m_lisActionNodes[i]).sActionConfig;
            }
            else if(m_lisActionNodes[i].GetType() == typeof(Action_Sing)){
                actionId = ((Action_Sing)m_lisActionNodes[i]).sActionConfig;
            }
            else if(m_lisActionNodes[i].GetType() == typeof(Action_DoBuffer))
            {
                //Buf  生效时候的特效
                Action_DoBuffer doBuf = m_lisActionNodes[i] as Action_DoBuffer;
                for (int j = 0; j < doBuf.lisBufDmg.Count; j++)
                {
                    effPath = GetEffPath(doBuf.lisBufDmg[j].bufConfig.heroBatEffectId);
                    if (effPath != null && !modelPath.Contains(effPath))
                        modelPath.Add(effPath);
                }
            }
            if(actionId != null)
            {
                effPath = GetEffPath(actionId.action1EffId);
                if (effPath != null && !modelPath.Contains(effPath))
                    modelPath.Add(effPath);

                effPath = GetEffPath(actionId.action2EffId);
                if (effPath != null && !modelPath.Contains(effPath))
                    modelPath.Add(effPath);

                effPath = GetEffPath(actionId.action3EffId);
                if (effPath != null && !modelPath.Contains(effPath))
                    modelPath.Add(effPath);

                effPath = GetEffPath(actionId.hitEffId);
                if (effPath != null && !modelPath.Contains(effPath))
                    modelPath.Add(effPath);
            }
        }


        m_iEffectRes = modelPath.Count;
        for (int i = 0; i < modelPath.Count; i++)
        {
            string path = modelPath[i];
            AEResources.Load(path, typeof(GameObject), delegate (UnityEngine.Object obj)
            {
                m_iEffectRes--;
                GameObject gObj = obj as GameObject;
                m_DicEffect.Add(modelPath[i], gObj);
                if (m_iEffectRes == 0)
                {
                    LoadDone();
                }
            });
        }
        if(m_iEffectRes == 0)
        {
            LoadDone();
        }
    }
    private string GetEffPath(int effId)
    {
        if(effId != 0)
        {
            HeroEff config = ConfigManager.Instance.heroEffLoader.GetInfoById(effId);
            if(config != null)
            {
                return config.path;
            }
        }

        return null;
    }

    //检查美术资源是否全部加载完毕
    private void LoadDone()
    {
        if (m_iEffectRes == 0 && m_iEffectRes!= m_iNotReadyLoad && 
            m_iSpineRes == 0 && m_iSpineRes!= m_iNotReadyLoad)
        {
            m_iEffectRes = m_iNotReadyLoad;
            m_iSpineRes = m_iNotReadyLoad;
            //创建英雄
            CreateHero();
            //todo 特效对象池子

            if (m_funcLoadDone != null)
            {
                m_funcLoadDone();
            }
        }
    }

    #endregion

    #region 统一管理带时间缩放的逻辑计时器
    //逻辑计时器
    private int m_iTimerId = 100;
    List<TimerVo> m_lisTimer = new List<TimerVo>();
    List<TimerVo> m_lisAdder = new List<TimerVo>();
    List<TimerVo> m_lisRemoveIds = new List<TimerVo>();
    

    private void UpTimer(float deltaTime)
    {
        if (m_lisAdder.Count > 0)
        {
            for (int i = 0; i < m_lisAdder.Count; i++)
            {
                m_lisTimer.Add(m_lisAdder[i]);
            }
            m_lisAdder.Clear();
        }

        for (int i = 0; i < m_lisTimer.Count; i++)
        {
            m_lisTimer[i].passTime += deltaTime;
            if (m_lisTimer[i].passTime >= m_lisTimer[i].duration)
            {
                m_lisTimer[i].action();
                m_lisRemoveIds.Add(m_lisTimer[i]);
            }
        }
        if (m_lisRemoveIds.Count > 0)
        {
            for (int i = 0; i < m_lisRemoveIds.Count; i++)
            {
                Debug.LogFormat("Timer-删除 : {0}", m_lisRemoveIds[i].ToString());
                m_lisTimer.Remove(m_lisRemoveIds[i]);
            }
            m_lisRemoveIds.Clear();
        }
    }
    public int AddTimer(Action action, float delay,string toString = "")
    {
        m_iTimerId++;
        TimerVo vo = new TimerVo(m_iTimerId, action, delay,toString);
        m_lisAdder.Add(vo);
        return vo.id;
    }

    public void DelTimer(int id)
    {
        for (int i = 0; i < m_lisTimer.Count; i++)
        {
            if(m_lisTimer[i].id == id &&
               !m_lisRemoveIds.Contains(m_lisTimer[i]))
            {
                m_lisRemoveIds.Add(m_lisTimer[i]);
            }
        }
    }
    public class TimerVo
    {
        public int id;//终止清除
        public Action action;
        public float duration;
        public float passTime;
        public string toString;

        public TimerVo(int id, Action action, float duration,string toString)
        {
            this.id = id;
            this.action = action;
            this.duration = duration;
            this.toString = toString;
            passTime = 0;
        }

        public override string ToString()
        {
            return toString;
        }
    }
    #endregion
}

